package cn.com.support.context;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.springframework.stereotype.Component;

import cn.com.commons.utils.NumberUtil;
import cn.com.dal.dataobject.sys.MenuDO;

/**
 * 菜单上下文
 * 
 * @since 2012-3-19 下午9:18:47
 * @version 1.0
 * @author Microbun
 * 
 */
@Component
public class MenuContext {

	private List<MenuDO> menusList;

	private MenuDO[] menuArray;

	private MenuDO[] rootMenu;

	/**
	 * 放入所有菜单(同时会更新AuthenticationContext)
	 * 
	 * @param menus
	 */
	public void putAllMenus(List<MenuDO> menus) {
		// 重置菜单权限
		AuthenticationContext.resetMenus(menus);
		synchronized (menus) {
			rootMenu = null;
			menusList = menus;
			buildMenuTree(menus);
		}
	}

	/**
	 * 获取所有的只读的菜单集合
	 * 
	 * @return
	 */
	public List<MenuDO> getReadOnlyMenus() {
		return Collections.unmodifiableList(menusList);
	}

	/**
	 * 返回根菜单
	 * 
	 * @return
	 */
	public MenuDO[] getRoot() {
		return rootMenu;
	}

	/**
	 * 根据ID获取菜单
	 * 
	 * @param id
	 * @return
	 */
	public MenuDO getMenuById(int id) {
		return menuArray[id];
	}

	/**
	 * 为菜单建立树层结构，并返回顶级菜单
	 * 
	 * @param menus
	 *            需要建立树结构的菜单
	 * @return 返回顶级菜单
	 */
	private void buildMenuTree(List<MenuDO> menus) {
		if (rootMenu == null) {
			MenuDO maxIdMenu = Collections.max(menus, new Comparator<MenuDO>() {
				@Override
				public int compare(MenuDO o1, MenuDO o2) {
					return (int) (o1.getId() - o2.getId());
				}

			});
			List<MenuDO> tempRoot = new ArrayList<MenuDO>();
			menuArray = new MenuDO[maxIdMenu.getId().intValue() + 1];
			for (MenuDO menu : menus) {
				menuArray[menu.getId().intValue()] = menu;
			}

			MenuDO child = null;
			MenuDO parent = null;
			for (int i = 1; i < menuArray.length; i++) {
				child = menuArray[i];
				if (child==null){continue;}
				if (NumberUtil.isPositive(menuArray[i].getParentId())) {
					parent = menuArray[child.getParentId().intValue()];
					if (parent==null){
						tempRoot.add(menuArray[i]);
						continue;
					}
					List<MenuDO> children = parent.getChildren();
					if (children == null) {
						children = new ArrayList<MenuDO>();
						parent.setChildren(children);
					}
					parent.getChildren().add(child);
				} else {
					tempRoot.add(menuArray[i]);
				}
				child = null;
				parent = null;
			}
			rootMenu=new MenuDO[tempRoot.size()];
			tempRoot.toArray(rootMenu);
		}
	}

	private static class Single {
		private final static MenuContext instance = new MenuContext();
	}

	public static MenuContext getInstance() {
		return Single.instance;
	}

}
